package labox.innovation.gameserver.model.itemcontainer;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.logging.Level;

import javolution.util.FastList;
import labox.innovation.config.Config;
import labox.innovation.db.ItemsDb;
import labox.innovation.db.core.L2DatabaseFactory;
import labox.innovation.gameserver.datatables.ItemTable;
import labox.innovation.gameserver.model.DropItemSelectInterface;
import labox.innovation.gameserver.model.FuzeWorld;
import labox.innovation.gameserver.model.L2ItemInstance;
import labox.innovation.gameserver.model.L2Object;
import labox.innovation.gameserver.model.TradeList;
import labox.innovation.gameserver.model.L2ItemInstance.ItemLocation;
import labox.innovation.gameserver.model.TradeList.TradeItem;
import labox.innovation.gameserver.model.actor.instance.FuzePcInstance;
import labox.innovation.gameserver.network.SystemMessageId;
import labox.innovation.gameserver.network.serverpackets.InventoryUpdate;
import labox.innovation.gameserver.network.serverpackets.ItemList;
import labox.innovation.gameserver.network.serverpackets.StatusUpdate;
import labox.innovation.gameserver.network.serverpackets.SystemMessage;
import labox.innovation.gameserver.templates.item.FuzeEconomicManager;
import labox.innovation.gameserver.templates.item.L2EtcItem;
import labox.innovation.gameserver.templates.item.L2EtcItemType;
import labox.innovation.gameserver.templates.item.L2Item;
import labox.innovation.gameserver.templates.item.FuzeEconomicManager.OPSTATE;

/**
 * 角色背包
 * 
 * @author zjj
 * 
 */
public class PcInventory extends Inventory {

	public static final int MAX_ADENA = 999000000;

	public static final int MONEY_SLIVER_ID = 20000; // 银文的模板id

	public static final int MONEY_NOTE_ID = 20001; // 银票的模板id

	public static final int MONEY_YAUNBAO_ID = 20002;// 元宝模板id

	public static final int MONEY_POINT_ID = 20003;// 积分模板id

	private L2ItemInstance _moneySliver; // 银子

	private L2ItemInstance _moneyNote; // 银票

	private L2ItemInstance _moneyYuanBao; // 元宝

	private L2ItemInstance _moneyPoint; // 积分

	private final FuzePcInstance _owner;
	
	private List<L2ItemInstance> _allExpItems;

	/**
	 * 物品掉落过滤器
	 */
	private DropItemSelectInterface _dropItemSelect;

	/**
	 * 注册一个掉落过滤选择器
	 * 
	 * @param dropItemSelect
	 */
	public void registDropItemSelectInterface(DropItemSelectInterface dropItemSelect) {
		_dropItemSelect = dropItemSelect;
	}

	public void removeDropItemSelectInterface() {
		_dropItemSelect = null;
	}

	public PcInventory(FuzePcInstance owner) {
		_owner = owner;
	}

	@Override
	public FuzePcInstance getOwner() {
		return _owner;
	}

	@Override
	public ItemLocation getBaseLocation() {
		return ItemLocation.INVENTORY;
	}

	@Override
	protected ItemLocation getEquipLocation() {
		return ItemLocation.PAPERDOLL;
	}

	/**
	 * 获得 银文的实例
	 * 
	 * @return
	 */
	public L2ItemInstance getMoneySilverInstance() {
		return _moneySliver;
	}

	/**
	 * 获得积分实例
	 * 
	 * @return
	 */
	public L2ItemInstance getMoneyPointInstance() {
		return _moneyPoint;
	}

	/**
	 * 获得元宝实例
	 * 
	 * @return
	 */
	public L2ItemInstance getMoneyYubaoInstance() {
		return _moneyYuanBao;
	}

	@Override
	/**
	 *  获得银子数
	 */
	public int getMoneySilver() {
		return _moneySliver != null ? _moneySliver.getCount() : 0;
	}

	/**
	 * 获得积分数
	 * 
	 * @return
	 */
	public int getMoneyPoint() {

		return _moneyPoint != null ? _moneyPoint.getCount() : 0;

	}

	/**
	 * 获得银票数
	 * 
	 * @return
	 */
	public int getMoneyNote() {
		return _moneyNote != null ? _moneyNote.getCount() : 0;
	}

	/**
	 * 获得元宝数
	 * 
	 * @return
	 */
	public int getMoneyYuanBao() {
		return _moneyYuanBao != null ? _moneyYuanBao.getCount() : 0;
	}

	/**
	 * Returns the list of items in inventory available for transaction
	 * 
	 * @return L2ItemInstance : items in inventory 获得人物背包中的 唯一的物品
	 */
	public L2ItemInstance[] getUniqueItems(boolean allowAdena, boolean allowAncientAdena) {
		return getUniqueItems(allowAdena, allowAncientAdena, true);
	}

	/**
	 * 获得 银票的 实例
	 * 
	 * @return
	 */
	public L2ItemInstance getMoneyNoteInstance() {
		return _moneyNote;
	}

	/**
	 * ?
	 * 
	 * @param allowAdena
	 * @param allowAncientAdena
	 * @param onlyAvailable
	 * @return
	 */
	public L2ItemInstance[] getUniqueItems(boolean allowAdena, boolean allowAncientAdena, boolean onlyAvailable) {
		List<L2ItemInstance> list = new FastList<L2ItemInstance>();
		for (L2ItemInstance item : _items) {
			if ((!allowAdena && item.getItemId() == 57))
				continue;
			if ((!allowAncientAdena && item.getItemId() == 5575))
				continue;

			boolean isDuplicate = false;
			for (L2ItemInstance litem : list) {
				if (litem.getItemId() == item.getItemId()) {
					isDuplicate = true;
					break;
				}
			}

			if (!isDuplicate && (!onlyAvailable || (item.isSellable() && item.isAvailable(getOwner(), false, false)))) {
				list.add(item);
			}

		}

		return list.toArray(new L2ItemInstance[list.size()]);
	}

	/**
	 * Returns the list of items in inventory available for transaction Allows
	 * an item to appear twice if and only if there is a difference in
	 * enchantment level.
	 * 
	 * @return L2ItemInstance : items in inventory
	 */
	public L2ItemInstance[] getUniqueItemsByEnchantLevel(boolean allowAdena, boolean allowAncientAdena) {
		return getUniqueItemsByEnchantLevel(allowAdena, allowAncientAdena, true);
	}

	public L2ItemInstance[] getUniqueItemsByEnchantLevel(boolean allowAdena, boolean allowAncientAdena, boolean onlyAvailable) {
		List<L2ItemInstance> list = new FastList<L2ItemInstance>();
		for (L2ItemInstance item : _items) {
			if ((!allowAdena && item.getItemId() == 57))
				continue;
			if ((!allowAncientAdena && item.getItemId() == 5575))
				continue;

			boolean isDuplicate = false;
			for (L2ItemInstance litem : list)
				if ((litem.getItemId() == item.getItemId()) && (litem.getEnchantLevel() == item.getEnchantLevel())) {
					isDuplicate = true;
					break;
				}
			if (!isDuplicate && (!onlyAvailable || (item.isSellable() && item.isAvailable(getOwner(), false, false))))
				list.add(item);
		}

		return list.toArray(new L2ItemInstance[list.size()]);
	}

	/**
	 * Returns the list of all items in inventory that have a given item id.
	 * 
	 * @return L2ItemInstance[] : matching items from inventory 返回背包中，
	 *         所有物品id为指定id的物品道具
	 */
	public L2ItemInstance[] getAllItemsByItemId(int itemId) {
		List<L2ItemInstance> list = new FastList<L2ItemInstance>();
		for (L2ItemInstance item : _items) {
			if (item.getItemId() == itemId)
				list.add(item);
		}

		return list.toArray(new L2ItemInstance[list.size()]);
	}

	/**
	 * Returns the list of all items in inventory that have a given item id AND
	 * a given enchantment level.
	 * 
	 * @return L2ItemInstance[] : matching items from inventory 返回背包中，
	 *         所有物品id为指定id 和 强化等级的物品道具
	 */
	public L2ItemInstance[] getAllItemsByItemId(int itemId, int enchantment) {
		List<L2ItemInstance> list = new FastList<L2ItemInstance>();
		for (L2ItemInstance item : _items) {
			if ((item.getItemId() == itemId) && (item.getEnchantLevel() == enchantment))
				list.add(item);
		}

		return list.toArray(new L2ItemInstance[list.size()]);
	}

	/**
	 * 获得所有可寄售的物品
	 * 
	 * @return
	 */
	public L2ItemInstance[] getAllConsignmentDatas() {
		List<L2ItemInstance> list = new FastList<L2ItemInstance>();
		for (L2ItemInstance item : _items) {

			if( item.isMoney() && item.getItemId() == MONEY_YAUNBAO_ID ){
				list.add(item);
			}
			else if (item != null && !item.isMoney() && !item.isEquipped() && item.isTradeable() && !item.isBinding() && item.isDropable() && item.isDepositable()) {
				list.add(item);
			}

		}

		return list.toArray(new L2ItemInstance[list.size()]);
	}

	/**
	 * Returns the list of items in inventory available for transaction 获得
	 * 背包中可以交易的有效物品?
	 * 
	 * @return L2ItemInstance : items in inventory
	 */
	public L2ItemInstance[] getAvailableItems(boolean allowAdena, boolean allowNonTradeable) {
		List<L2ItemInstance> list = new FastList<L2ItemInstance>();
		for (L2ItemInstance item : _items)
			if (item != null && item.isAvailable(getOwner(), allowAdena, allowNonTradeable)){
				
				if( !allowNonTradeable && item.isBinding() ){
					continue;
				}
				
				list.add(item);
			}

		return list.toArray(new L2ItemInstance[list.size()]);
	}

	/**
	 * 获得背包里的可使用物品 装备， 不能使用的物品 都不返回
	 * 
	 * @return
	 */
	public L2ItemInstance[] getCanUseItems() {
		List<L2ItemInstance> list = new FastList<L2ItemInstance>();

		for (L2ItemInstance item : _items) {
			if (!item.isEtcItem() || item.isEquipped() || !item.getItem().getCanuse()) {
				continue;
			}

			list.add(item);
		}

		return list.toArray(new L2ItemInstance[list.size()]);
	}

	/**
	 * Get all augmented items 获得所有精炼过的物品
	 * 
	 * @return
	 */
	public L2ItemInstance[] getAugmentedItems() {
		// List<L2ItemInstance> list = new FastList<L2ItemInstance>();
		// for (L2ItemInstance item : _items)
		// if (item != null && item.isAugmented()) list.add(item);
		//
		// return list.toArray(new L2ItemInstance[list.size()]);
		return null;
	}

	/**
	 * Get all element items 获得所有有元 素属性的物品
	 * 
	 * @return
	 */
	public L2ItemInstance[] getElementItems() {
		List<L2ItemInstance> list = new FastList<L2ItemInstance>();
		// for (L2ItemInstance item : _items) {
		// if (item != null && item.getElementals() != null)
		// list.add(item);
		// }
		return list.toArray(new L2ItemInstance[list.size()]);
	}

	/**
	 * Returns the list of items in inventory available for transaction adjusted
	 * by tradeList
	 * 
	 * @return L2ItemInstance : items in inventory ?
	 */
	public TradeList.TradeItem[] getAvailableItems(TradeList tradeList) {
		List<TradeList.TradeItem> list = new FastList<TradeList.TradeItem>();
		for (L2ItemInstance item : _items)
			if (item.isAvailable(getOwner(), false, false)) {
				TradeList.TradeItem adjItem = tradeList.adjustAvailableItem(item);
				if (adjItem != null)
					list.add(adjItem);
			}

		return list.toArray(new TradeList.TradeItem[list.size()]);
	}

	/**
	 * Adjust TradeItem according his status in inventory
	 * 
	 * @param item
	 *            : L2ItemInstance to be adjusten
	 * @return TradeItem representing adjusted item
	 */
	public void adjustAvailableItem(TradeItem item) {
		boolean notAllEquipped = false;
		for (L2ItemInstance adjItem : getItemsByItemId(item.getItem().getItemId())) {
			if (adjItem.isEquipable()) {
				if (!adjItem.isEquipped())
					notAllEquipped |= true;
			} else {
				notAllEquipped |= true;
				break;
			}
		}
		if (notAllEquipped) {
			L2ItemInstance adjItem = getItemByItemId(item.getItem().getItemId());
			item.setObjectId(adjItem.getObjectId());
			item.setEnchant(adjItem.getEnchantLevel());

			if (adjItem.getCount() < item.getCount())
				item.setCount(adjItem.getCount());

			return;
		}

		item.setCount(0);
	}

	/**
	 * Adds adena to PCInventory
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param count
	 *            : int Quantity of adena to be added
	 * @param actor
	 *            : L2PcInstance Player requesting the item add
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling
	 *            item or previous item in transformation
	 */
	/*
	 * @param process : 怎么来的
	 * 
	 * @param count ： 数量
	 * 
	 * @param actor : 增加的人
	 * 
	 * @param reference : 来自哪的
	 */
	public void addMoneySilver(String process, int count, FuzePcInstance actor, L2Object reference) {
		if (count > 0)
			addItem(process, MONEY_SLIVER_ID, count, actor, reference);
	}

	/**
	 * 增加积分
	 * 
	 * @param process
	 * @param count
	 * @param actor
	 * @param reference
	 */
	public void addMoneyPoint(String process, int count, FuzePcInstance actor, L2Object reference) {
		if (count > 0) {
			addItem(process, MONEY_POINT_ID, count, actor, reference);
		}
	}

	/**
	 * 减少积分
	 * 
	 * @param process
	 * @param count
	 * @param actor
	 * @param reference
	 */
	public void reduceMoneyPoint(String process, int count, FuzePcInstance actor, L2Object reference) {
		if (count > 0)
			destroyItemByItemId(process, MONEY_POINT_ID, count, actor, reference);
	}

	/**
	 * 背包中是否有 足够的的钱. 银文.
	 * 
	 * @param process
	 * @param actor
	 * @param needMoney
	 *            : 需要的银文数
	 * @return
	 */
	public boolean hasEnoughSilverMoney(String process, FuzePcInstance actor, int needMoney) {
		return FuzeEconomicManager.getInstance().hasEnoughSilverMoney(_owner, process, needMoney);
	}

	/**
	 * Removes adena to PCInventory
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param count
	 *            : int Quantity of adena to be removed
	 * @param actor
	 *            : L2PcInstance Player requesting the item add
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling
	 *            item or previous item in transformation
	 */
	/*
	 * @param process : 减钱的原因 或者 玩家的某些操作
	 * 
	 * @param count ： 数量
	 * 
	 * @param actor : 减钱 的角色
	 * 
	 * @param reference : 来自哪的
	 */
	public void reduceMoneySilver(String process, int count, FuzePcInstance actor, L2Object reference) {
		// if (count > 0)
		// destroyItemByItemId(process, MONEY_SLIVER_ID, count, actor,
		// reference);
		if (count > 0) {
			FuzeEconomicManager.getInstance().reduceSilverMoney(_owner, process, count, reference);
		}
	}

	/**
	 * 减少银文. 这个接口 外面不需要直接调用, 如果直接调用这个 接口 将不会 通过经济系统的验证 直接扣钱
	 * 
	 * @param process
	 *            : 减钱的原因 或者 玩家的某些操作
	 * @param count
	 * @param actor
	 * @param reference
	 */
	public void reduceMoneySilverDirectly(String process, int count, FuzePcInstance actor, L2Object reference) {
		if (count > 0 && _moneySliver != null) {

			L2ItemInstance moneyItem = destroyItemByItemId(process, MONEY_SLIVER_ID, count, actor, reference);

			// InventoryUpdate iu = new InventoryUpdate();
			// iu.addItem(moneyItem);
			// actor.sendPacket(iu);
			//
			// SystemMessage sm = new
			// SystemMessage(SystemMessageId.DISAPPEARED_ADENA);
			// sm.addItemNumber(count);
			// actor.sendPacket(sm);

		}

	}

	/**
	 * Adds specified amount of ancient adena to player inventory.
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param count
	 *            : int Quantity of adena to be added
	 * @param actor
	 *            : L2PcInstance Player requesting the item add
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling
	 *            item or previous item in transformation
	 */

	/*
	 * @param process : 怎么来的
	 * 
	 * @param count ： 数量
	 * 
	 * @param actor : 增加的人
	 * 
	 * @param reference : 来自哪的
	 */
	public void addMoneyNote(String process, int count, FuzePcInstance actor, L2Object reference) {
		if (count > 0)
			addItem(process, MONEY_NOTE_ID, count, actor, reference);
	}

	/**
	 * Removes specified amount of ancient adena from player inventory.
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param count
	 *            : int Quantity of adena to be removed
	 * @param actor
	 *            : L2PcInstance Player requesting the item add
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling
	 *            item or previous item in transformation
	 */
	/*
	 * @param process : 怎么来的
	 * 
	 * @param count ： 数量
	 * 
	 * @param actor : 增加的人
	 * 
	 * @param reference : 来自哪的
	 */
	public void reduceMoneyNote(String process, int count, FuzePcInstance actor, L2Object reference) {
		if (count > 0)
			destroyItemByItemId(process, MONEY_NOTE_ID, count, actor, reference);
	}

	/**
	 * 
	 * @param process
	 *            : 怎么来的
	 * @param count
	 *            ： 数量
	 * @param actor
	 *            : 增加的人
	 * @param reference
	 *            : 来自哪的
	 */
	public void addMoneyYuanBao(String process, int count, FuzePcInstance actor, L2Object reference) {
		if (count > 0) {
			addItem(process, MONEY_YAUNBAO_ID, count, actor, reference);
		}
	}

	/**
	 * 减少元宝的数量
	 * 
	 * @param process
	 * @param count
	 *            : 减少的数
	 * @param actor
	 * @param reference
	 */
	public void reduceMoneyYuanBao(String process, int count, FuzePcInstance actor, L2Object reference) {
		if (count > 0) {
			destroyItemByItemId(process, MONEY_YAUNBAO_ID, count, actor, reference);
		}
	}

	/**
	 * Adds item in inventory and checks _adena and _ancientAdena
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param item
	 *            : L2ItemInstance to be added
	 * @param actor
	 *            : L2PcInstance Player requesting the item add
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling
	 *            item or previous item in transformation
	 * @return L2ItemInstance corresponding to the new item or the updated item
	 *         in inventory
	 */
	@Override
	public L2ItemInstance addItem(String process, L2ItemInstance item, FuzePcInstance actor, L2Object reference) {
		if (_dropItemSelect != null && !_dropItemSelect.canSelect(process, item, reference)) {
			ItemTable.getInstance().destroyItem("过滤拾取", item, actor, reference);
			return null;
		}
		item = super.addItem(process, item, actor, reference);

		// if (item != null && item.getItemId() == ADENA_ID &&
		// !item.equals(_adena))
		// _adena = item;
		//
		// if (item != null && item.getItemId() == ANCIENT_ADENA_ID &&
		// !item.equals(_ancientAdena))
		// _ancientAdena = item;
		
		addNewItemStoreExp( item );

		if (item != null && item.getItemId() == MONEY_SLIVER_ID && !item.equals(_moneySliver)) {
			_moneySliver = item;
			restInventorySlot(item.getLocationSlot());
			_moneySliver.setLocation(getBaseLocation(), -1);
		} else if (item != null && item.getItemId() == MONEY_NOTE_ID && !item.equals(_moneySliver)) {
			_moneyNote = item;
			restInventorySlot(item.getLocationSlot());
			_moneyNote.setLocation(getBaseLocation(), -1);
		} else if (item != null && item.getItemId() == MONEY_YAUNBAO_ID && !item.equals(_moneyYuanBao)) {
			_moneyYuanBao = item;
			restInventorySlot(item.getLocationSlot());
			_moneyYuanBao.setLocation(getBaseLocation(), -1);
		} else if (item != null && item.getItemId() == MONEY_POINT_ID && !item.equals(_moneyPoint)) {
			_moneyPoint = item;
			restInventorySlot(item.getLocationSlot());
			_moneyPoint.setLocation(getBaseLocation(), -1);
		}

		return item;
	}
	
	
	protected void addNewItemStoreExp( L2ItemInstance item ){
		
		//如果是增加经验的道具 ， 那么把这个道具加入到 经验道具容器中
		if( item != null && item.isStoreExpItem() ){
			
			if( _allExpItems == null ){
				_allExpItems = new FastList<L2ItemInstance>();
			}
			
			if( _allExpItems.contains(item) ){
				return;
			}
			
			int index = 0;
			for( L2ItemInstance it : _allExpItems ){
				if( it.getLocationSlot() > item.getLocationSlot() ){
					break;
				}
				index++;
			}

			_allExpItems.add(index, item);
			if( _log.isDebugEnabled() ){
				_log.debug("加入累积经验符的道具:" + index + "物品:" + item );
			}
			
		}
		
	}
	
	protected void removeNewItemStoreExp( L2ItemInstance item ){
		
		if( item != null && item.isStoreExpItem() ){
			
			if( _allExpItems != null ){
				_allExpItems.remove(item);
			}
			
		}
		
	}
	
	/**
	 * 更新 存储的经验值
	 * @param val
	 */
	public void notifyStoreExp( int val ){
		
		if( _allExpItems != null && _allExpItems.size() > 0 ){

			
			L2ItemInstance item = _allExpItems.get( 0 );
			val = (int) (val * ( (L2EtcItem)item.getItem() ).getStoreExpRadio());
			item.updateStoreExp( val ) ;
			
			if( _log.isDebugEnabled() )
			{
				_log.debug("往经验球中 增加经验:" + val );
			}
			
			if( item.getStoreExp() >= ( (L2EtcItem)item.getItem() ).getMaxStoreExp() ){
				_allExpItems.remove( item );
			}
		}
		
	}// end notifyStoreExp
	
	

	/**
	 * Adds item in inventory and checks _adena and _ancientAdena
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param itemId
	 *            : int Item Identifier of the item to be added
	 * @param count
	 *            : int Quantity of items to be added
	 * @param actor
	 *            : L2PcInstance Player requesting the item creation
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling
	 *            item or previous item in transformation
	 * @return L2ItemInstance corresponding to the new item or the updated item
	 *         in inventory
	 */
	@Override
	public L2ItemInstance addItem(String process, int itemId, int count, FuzePcInstance actor, L2Object reference) {
		if (_dropItemSelect != null && !_dropItemSelect.canSelect(process, itemId, reference)) {
			_log.info("道具被过滤:" +  "物品id:" + itemId + "物品数量:" + count + "物品拥有者"+ actor.getName()+ "(" + actor.getObjectId() + ")", itemId, ItemTable.getInstance().getTemplate(itemId).getName() );
			return null;
		}
		L2ItemInstance item = super.addItem(process, itemId, count, actor, reference);

		// if (item != null && item.getItemId() == ADENA_ID &&
		// !item.equals(_adena))
		// _adena = item;
		//
		// if (item != null && item.getItemId() == ANCIENT_ADENA_ID &&
		// !item.equals(_ancientAdena))
		// _ancientAdena = item;
		
		addNewItemStoreExp( item );

		if (item != null && item.getItemId() == MONEY_SLIVER_ID && !item.equals(_moneySliver)) {
			_moneySliver = item;
			restInventorySlot(item.getLocationSlot());
			_moneySliver.setLocation(getBaseLocation(), -1);
		} else if (item != null && item.getItemId() == MONEY_NOTE_ID && !item.equals(_moneySliver)) {
			_moneyNote = item;
			restInventorySlot(item.getLocationSlot());
			_moneyNote.setLocation(getBaseLocation(), -1);
		} else if (item != null && item.getItemId() == MONEY_YAUNBAO_ID && !item.equals(_moneyYuanBao)) {
			_moneyYuanBao = item;
			restInventorySlot(item.getLocationSlot());
			_moneyYuanBao.setLocation(getBaseLocation(), -1);
		} else if (item != null && item.getItemId() == MONEY_POINT_ID && !item.equals(_moneyPoint)) {
			_moneyPoint = item;
			restInventorySlot(item.getLocationSlot());
			_moneyPoint.setLocation(getBaseLocation(), -1);
		}

		// if (item != null && actor != null) {
		// // Send inventory update packet
		// // if (!Config.FORCE_INVENTORY_UPDATE) {
		// // InventoryUpdate playerIU = new InventoryUpdate();
		// // playerIU.addItem(item);
		// // actor.sendPacket(playerIU);
		// // } else
		// // actor.sendPacket(new ItemList(actor, false));
		// }

		return item;
	}

	/**
	 * Transfers item to another inventory and checks _adena and _ancientAdena
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param itemId
	 *            : int Item Identifier of the item to be transfered
	 * @param count
	 *            : int Quantity of items to be transfered
	 * @param actor
	 *            : L2PcInstance Player requesting the item transfer
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling
	 *            item or previous item in transformation
	 * @return L2ItemInstance corresponding to the new item or the updated item
	 *         in inventory
	 */
	@Override
	public L2ItemInstance transferItem(String process, long objectId, int count, ItemContainer target, FuzePcInstance actor, L2Object reference) {
		process = process + ",";
		L2ItemInstance item = super.transferItem(process, objectId, count, target, actor, reference);

		// if (_adena != null && (_adena.getCount() <= 0 || _adena.getOwnerId()
		// != getOwnerId()))
		// _adena = null;
		//
		// if (_ancientAdena != null && (_ancientAdena.getCount() <= 0 ||
		// _ancientAdena.getOwnerId() != getOwnerId()))
		// _ancientAdena = null;

		if( item != null && !_items.contains( item ) ){
			removeNewItemStoreExp(item);
		}
		
		if (_moneySliver != null && (_moneySliver.getCount() <= 0 || _moneySliver.getOwnerId() != getOwnerId())) {
			_moneySliver = null;
		} else if (_moneyNote != null && (_moneyNote.getCount() <= 0 || _moneyNote.getOwnerId() != getOwnerId())) {
			_moneyNote = null;
		} else if (_moneyYuanBao != null && (_moneyYuanBao.getCount() <= 0 || _moneyYuanBao.getOwnerId() != getOwnerId())) {
			_moneyYuanBao = null;
		} else if (_moneyPoint != null && (_moneyPoint.getCount() <= 0 || _moneyPoint.getOwnerId() != getOwnerId())) {
			_moneyPoint = null;
		}

		return item;
	}

	/**
	 * Destroy item from inventory and checks _adena and _ancientAdena
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param item
	 *            : L2ItemInstance to be destroyed
	 * @param actor
	 *            : L2PcInstance Player requesting the item destroy
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling
	 *            item or previous item in transformation
	 * @return L2ItemInstance corresponding to the destroyed item or the updated
	 *         item in inventory
	 */
	@Override
	public L2ItemInstance destroyItem(String process, L2ItemInstance item, FuzePcInstance actor, L2Object reference) {
		return this.destroyItem(process, item, item.getCount(), actor, reference);
	}

	/**
	 * Destroy item from inventory and checks _adena and _ancientAdena
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param item
	 *            : L2ItemInstance to be destroyed
	 * @param actor
	 *            : L2PcInstance Player requesting the item destroy
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling
	 *            item or previous item in transformation
	 * @return L2ItemInstance corresponding to the destroyed item or the updated
	 *         item in inventory
	 */
	@Override
	public L2ItemInstance destroyItem(String process, L2ItemInstance item, int count, FuzePcInstance actor, L2Object reference) {
		if (item == null) {
			return item;
		}
		int oldSolt = item.getLocationSlot();

		item = super.destroyItem(process, item, count, actor, reference);

		if (item != null && item.getCount() <= 0) {
			restInventorySlot(oldSolt);
			removeNewItemStoreExp(item);
		}

		// if (_adena != null && _adena.getCount() <= 0)
		// _adena = null;
		//
		// if (_ancientAdena != null && _ancientAdena.getCount() <= 0)
		// _ancientAdena = null;

		if (_moneySliver != null && (_moneySliver.getCount() <= 0)) {
			_moneySliver = null;
		} else if (_moneyNote != null && (_moneyNote.getCount() <= 0)) {
			_moneyNote = null;
		} else if (_moneyYuanBao != null && (_moneyYuanBao.getCount() <= 0)) {
			_moneyYuanBao = null;
		} else if (_moneyPoint != null && (_moneyPoint.getCount() <= 0)) {
			_moneyPoint = null;
		}

		return item;
	}

	/**
	 * Destroys item from inventory and checks _adena and _ancientAdena
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param objectId
	 *            : int Item Instance identifier of the item to be destroyed
	 * @param count
	 *            : int Quantity of items to be destroyed
	 * @param actor
	 *            : L2PcInstance Player requesting the item destroy
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling
	 *            item or previous item in transformation
	 * @return L2ItemInstance corresponding to the destroyed item or the updated
	 *         item in inventory
	 */
	@Override
	public L2ItemInstance destroyItem(String process, long objectId, int count, FuzePcInstance actor, L2Object reference) {
		L2ItemInstance item = getItemByObjectId(objectId);
		if (item == null) {
			return null;
		}
		return this.destroyItem(process, item, count, actor, reference);
	}

	/**
	 * Destroy item from inventory by using its <B>itemId</B> and checks _adena
	 * and _ancientAdena
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param itemId
	 *            : int Item identifier of the item to be destroyed
	 * @param count
	 *            : int Quantity of items to be destroyed
	 * @param actor
	 *            : L2PcInstance Player requesting the item destroy
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling
	 *            item or previous item in transformation
	 * @return L2ItemInstance corresponding to the destroyed item or the updated
	 *         item in inventory
	 */
	@Override
	public L2ItemInstance destroyItemByItemId(String process, int itemId, int count, FuzePcInstance actor, L2Object reference) {
		L2ItemInstance item = getItemByItemId(itemId);
		if (item == null) {
			return null;
		}
		return this.destroyItem(process, item, count, actor, reference);
	}

	/**
	 * Drop item from inventory and checks _adena and _ancientAdena
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param item
	 *            : L2ItemInstance to be dropped
	 * @param actor
	 *            : L2PcInstance Player requesting the item drop
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling
	 *            item or previous item in transformation
	 * @return L2ItemInstance corresponding to the destroyed item or the updated
	 *         item in inventory
	 */
	@Override
	public L2ItemInstance dropItem(String process, L2ItemInstance item, FuzePcInstance actor, L2Object reference) {
		int oldSlot = item.getLocationSlot();

		item = super.dropItem(process, item, actor, reference);

		if ( item != null && !item.isEquipped() ) {
			restInventorySlot(oldSlot);
		}
		
		removeNewItemStoreExp(item);

		// if (_adena != null && (_adena.getCount() <= 0 || _adena.getOwnerId()
		// != getOwnerId()))
		// _adena = null;
		//
		// if (_ancientAdena != null && (_ancientAdena.getCount() <= 0 ||
		// _ancientAdena.getOwnerId() != getOwnerId()))
		// _ancientAdena = null;

		if (_moneySliver != null && (_moneySliver.getCount() <= 0 || _moneySliver.getOwnerId() != getOwnerId())) {
			_moneySliver = null;
		} else if (_moneyNote != null && (_moneyNote.getCount() <= 0 || _moneyNote.getOwnerId() != getOwnerId())) {
			_moneyNote = null;
		} else if (_moneyYuanBao != null && (_moneyYuanBao.getCount() <= 0)) {
			_moneyYuanBao = null;
		} else if (_moneyPoint != null && (_moneyPoint.getCount() <= 0)) {
			_moneyPoint = null;
		}

		return item;
	}

	/**
	 * Drop item from inventory by using its <B>objectID</B> and checks _adena
	 * and _ancientAdena
	 * 
	 * @param process
	 *            : String Identifier of process triggering this action
	 * @param objectId
	 *            : int Item Instance identifier of the item to be dropped
	 * @param count
	 *            : int Quantity of items to be dropped
	 * @param actor
	 *            : L2PcInstance Player requesting the item drop
	 * @param reference
	 *            : L2Object Object referencing current action like NPC selling
	 *            item or previous item in transformation
	 * @return L2ItemInstance corresponding to the destroyed item or the updated
	 *         item in inventory
	 */
	@Override
	public L2ItemInstance dropItem(String process, long objectId, int count, FuzePcInstance actor, L2Object reference) {
		L2ItemInstance item = super.dropItem(process, objectId, count, actor, reference);

		removeNewItemStoreExp(item);
		
		if (_moneySliver != null && (_moneySliver.getCount() <= 0 || _moneySliver.getOwnerId() != getOwnerId()))
			_moneySliver = null;

		if (_moneyNote != null && (_moneyNote.getCount() <= 0 || _moneyNote.getOwnerId() != getOwnerId()))
			_moneyNote = null;

		if (_moneyYuanBao != null && (_moneyYuanBao.getCount() <= 0 || _moneyYuanBao.getOwnerId() != getOwnerId()))
			_moneyYuanBao = null;

		if (_moneyPoint != null && (_moneyPoint.getCount() <= 0 || _moneyPoint.getOwnerId() != getOwnerId()))
			_moneyPoint = null;

		return item;
	}

	/**
	 * <b>Overloaded</b>, when removes item from inventory, remove also owner
	 * shortcuts.
	 * 
	 * @param item
	 *            : L2ItemInstance to be removed from inventory
	 */
	@Override
	public boolean removeItem(L2ItemInstance item) {
		// 从快捷栏上 移除这个物品
		getOwner().removeItemFromShortCut(item.getObjectId());

		// Removes active Enchant Scroll
		// if(item.equals(getOwner().getActiveEnchantItem()))
		// getOwner().setActiveEnchantItem(null);

		if (item.getItemId() == MONEY_SLIVER_ID)
			_moneySliver = null;
		else if (item.getItemId() == MONEY_NOTE_ID)
			_moneyNote = null;
		else if (item.getItemId() == MONEY_YAUNBAO_ID)
			_moneyYuanBao = null;

		return super.removeItem(item);
	}

	/**
	 * Refresh the weight of equipment loaded
	 */
	@Override
	public void refreshWeight() {
		super.refreshWeight();
		// getOwner().refreshOverloaded();
	}

	/**
	 * Get back items in inventory from database
	 */
	// @Override
	public void restore() {
		List<L2ItemInstance> _items = ItemsDb.restoreContainer(getOwnerId(), this);
		for (L2ItemInstance item : _items) {
//			if (getOwner() instanceof FuzePcInstance) {
//				FuzePcInstance player = (FuzePcInstance) getOwner();
//
//				if (player.getPkKills() > 0 && item.getItemId() >= 7816 && item.getItemId() <= 7831)
//					item.setLocation(ItemLocation.INVENTORY);
//
//				if (!player.isGM() && item.isHeroItem())
//					item.setLocation(ItemLocation.INVENTORY);
//			}
			// 物品不需要立即进入世界
			// FuzeWorld.getInstance().enterWorld(item);

			//add by zengjiejun
			//用来修复脏的数据。  如果 物品没装备,且物品的插槽位置为-1， 那么这个物品出错了。 不与恢复
			if( !item.isEquipped() && item.getLocationSlot() == -1 && !item.isMoney() ){
				continue;
			}
			if( item.getCount() <= 0 ){
				continue;
			}
			
			// If stackable item is found in inventory just add to current
			// quantity
			//zjj 修改 2010.7.15
			//不管物品是否能叠加 在数据从数据库督读出来后 直接加入到背包， 不需做其他处理
//			if (item.isStackable() && getItemByItemId(item.getItemId()) != null)
//				addItem("Restore", item, getOwner().getActingPlayer(), null);
//			else
//				addItem(item);
			
			addItem(item);
			
		}

		// }
		// inv.close();
		// statement.close();
		refreshWeight();
		_moneySliver = getItemByItemId(MONEY_SLIVER_ID);
		_moneyNote = getItemByItemId(MONEY_NOTE_ID);
		_moneyYuanBao = getItemByItemId(MONEY_YAUNBAO_ID);
		_moneyPoint = getItemByItemId(MONEY_POINT_ID);
	}
	
	protected void addItem(L2ItemInstance item) {
		
		super.addItem(item);
		
		addNewItemStoreExp(item);
	}

	/**
	 * 获得人物 可见的物品 从装备栏上看到的装备 一般来说
	 * 
	 * @param objectId
	 * @return
	 */
	public static int[][] restoreVisibleInventory(long objectId) {
		int[][] paperdoll = new int[31][3];
		Connection con = null;

		try {
			con = L2DatabaseFactory.getInstance().getConnection();
			PreparedStatement statement2 = con.prepareStatement("SELECT object_id,item_id,loc_data,enchant_level FROM items WHERE owner_id=? AND loc='PAPERDOLL'");
			statement2.setLong(1, objectId);
			ResultSet invdata = statement2.executeQuery();

			while (invdata.next()) {
				int slot = invdata.getInt("loc_data");
				paperdoll[slot][0] = invdata.getInt("object_id");
				paperdoll[slot][1] = invdata.getInt("item_id");
				paperdoll[slot][2] = invdata.getInt("enchant_level");
				if (slot == Inventory.PAPERDOLL_HAND) {
					paperdoll[Inventory.PAPERDOLL_HAND][0] = invdata.getInt("object_id");
					paperdoll[Inventory.PAPERDOLL_HAND][1] = invdata.getInt("item_id");
					paperdoll[Inventory.PAPERDOLL_HAND][2] = invdata.getInt("enchant_level");
				}
			}

			invdata.close();
			statement2.close();
		} catch (Exception e) {
			_log.error("could not restore inventory:", Config.SERVER_ID, e);
		} finally {
			try {
				con.close();
			} catch (Exception e) {
			}
		}
		return paperdoll;
	}

	/**
	 * 背包中 是否能放的下这个装备道具
	 * 
	 * @param item
	 * @return
	 */
	public boolean validateCapacity(L2ItemInstance item) {
//		int slots = 0;
//
//		if( item.isMoney() && item.getCount() < 0x7fffffff ){
//			return true;
//		}
//		
//		// 如果物品不能叠加 或者 背包中还没这个物品。 且物品不是药草 那么这个物品需要占一个新的格
//		if ( !item.isStackable() || getItemByItemId(item.getItemId() ) != null) 
//			slots++;

		return validateCapacityByItemId( item.getItemId() );
//		return validateCapacity(slots);
	}

	/**
	 * 背包中 是否能放的下这些 装备道具
	 * 
	 * @param items
	 * @return
	 */
	public boolean validateCapacity(List<L2ItemInstance> items) {
		int slots = 0;

		for (L2ItemInstance item : items)
			if ( !(item.isStackable() && getItemByItemId(item.getItemId()) != null) )
				slots++;

		return validateCapacity(slots);
	}

	/**
	 * 背包中 能否放的下这个物品
	 * 
	 * @param ItemId
	 * @return
	 */
	public boolean validateCapacityByItemId(int ItemId) {
//		int slots = 0;
//
//		L2ItemInstance invItem = getItemByItemId(ItemId);
//		if( invItem.isMoney() && invItem.getCount() < 0xffffffff ){
//			return true;
//		}
//		// 如果背包中不存在这个物品 或者 这个物品不可叠加 那么需要占一个新的格
//		if (invItem == null || !invItem.isStackable())
//			slots++;

		return validateCapacityByItemId( ItemId, 1 );
//		return validateCapacity(slots);
	}

	/**
	 * 背包中能否放下 count个数的物品.
	 * 
	 * @param ItemId
	 * @param count
	 * @return
	 */
	public boolean validateCapacityByItemId(int ItemId, int count) {
		int slots = 0;

		L2ItemInstance invItem = getItemByItemId(ItemId);
		L2Item item = ItemTable.getInstance().getTemplate(ItemId);

		if (item == null) {
			return false;
		}
		if( item.isMoney() && count < 0x7fffffff ){
			return true;
		}

		// 如果物品是可以堆叠的
		if (item.isStackable()) {

			// 物品存在 且 物品不能在叠加这么多数量, 或者 物品 不存在
			if ((invItem != null && !invItem.canStackable(count)) || invItem == null) {
				if (count > item.getMaxStackNums()) {

					int nums = (int) Math.ceil((float) count / item.getMaxStackNums());
					slots += nums;

				} else {
					slots += 1;
				}

			}

		} else {
			slots += count;
		}

		// // 如果背包中不存在这个物品 或者 这个物品不可叠加 那么需要占一个新的格
		// if ( invItem != null && !invItem.canStackable(count) ){
		// slots++;
		// }
		// else {
		// // L2Item item = ItemTable.getInstance().getTemplate(ItemId);
		// // 如果物品不能叠加
		// if (item != null && !item.isStackable()) {
		// slots += count;
		// }
		// else if( item != null )
		// {
		// slots++;
		// }
		// else
		// {
		// return false;
		// }
		// }

		// System.out.println("需要的插槽数:" + slots);
		return validateCapacity(slots);
	}

	/**
	 * 获得背包当前 容量 的大小
	 * 
	 * @return 背包容量大小
	 */
	public int getInventoryLimit() {
		return _maxCurrentSoltNums;
	}

	/**
	 * 验证背包大小
	 */
	@Override
	public boolean validateCapacity(int slots) {
		// return (_items.size() + slots <= _owner.getInventoryLimit());
		int nums = 0;
		if (_moneySliver != null) {
			nums += 1;
		}
		if (_moneyNote != null) {
			nums += 1;
		}
		if (_moneyYuanBao != null) {
			nums += 1;
		}
		if (_moneyPoint != null) {
			nums += 1;
		}
		return (_items.size() + slots - nums <= getInventoryLimit() + getEquipItems());
	}

	@Override
	public boolean validateWeight(int weight) {
		// return (_totalWeight + weight <= _owner.getMaxLoad());
		return true;
	}

	@Override
	public int getMaxCurrentSoltNums() {
		// TODO Auto-generated method stub
		return _maxCurrentSoltNums;
	}

	@Override
	public void setMaxCurrentSoltNums(int maxCurrentSoltNums) {
		if( maxCurrentSoltNums > MAX_SLOTS ){
			maxCurrentSoltNums = MAX_SLOTS;
		}
		_maxCurrentSoltNums = maxCurrentSoltNums;

	}

}
